group is package{
  type group is group{
    elem has kind type;
    
    zero has type elem;
    inv has type (elem)=>elem;
    op has type (elem,elem)=>elem;
    
    el has type for all %t such that (%t)=>elem;
  };
  
  modGroup(K) is group{
    type integer counts as elem;
    zero is 0;
    
    inv(X) is K-X;
    
    op(X,Y) is (X+Y)%K;
    
    el(X) is X cast elem;
  };
  
  double has type (group)=>group;
  double(G) is group{
    type G.elem counts as elem;
    
    zero is G.zero;
    
    inv(X) is G.inv(X);
    
    op(X,Y) is G.op(G.op(X,X),G.op(Y,Y));
    
    el(X) is G.el(X);
  }
  
  invGroup(G) is group{
    type G.elem counts as elem;
    
    zero is G.zero;
    
    inv is G.inv;
    
    op(X,Y) is G.inv(G.op(G.inv(X),G.inv(Y)));
    
    el is G.el
  }
  
  main() do {
    K is modGroup(7);
    logMsg(info,"K.zero=#(__display(K.zero))");
    logMsg(info,"3+5=#(__display(K.op(K.el(3),K.el(5))))");
    
    D is double(K);
    logMsg(info,"D.zero = #(__display(D.zero))");
    logMsg(info,"3+5=#(__display(D.op(D.el(3),D.el(5))))");
  }
}